home *** CD-ROM | disk | FTP | other *** search
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Calendar code.
- *
- * The Initial Developer of the Original Code is
- * Philipp Kewisch <mozilla@kewis.ch>
- * Portions created by the Initial Developer are Copyright (C) 2007
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Michiel van Leeuwen <mvl@exedo.nl>
- * Joey Minta <jminta@gmail.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
- /**
- * Calendar specific utility functions
- */
- var gCompositeCalendar = null;
- function getCompositeCalendar() {
- if (!gCompositeCalendar) {
- gCompositeCalendar =
- Components.classes["@mozilla.org/calendar/calendar;1?type=composite"]
- .createInstance(Components.interfaces.calICompositeCalendar);
-
- gCompositeCalendar.prefPrefix = 'calendar-main';
- }
- return gCompositeCalendar;
- }
-
- function getSelectedCalendar() {
- var tree = document.getElementById("calendar-list-tree");
- return (tree.currentIndex > -1) &&
- calendarListTreeView.mCalendarList[tree.currentIndex] || null;
- }
-
- function promptDeleteCalendar(aCalendar) {
- var calendars = getCalendarManager().getCalendars({});
- if (calendars.length <= 1) {
- // If this is the last calendar, don't delete it.
- return;
- }
-
- var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
- .getService(Components.interfaces.nsIPromptService);
- var ok = promptService.confirm(
- window,
- calGetString("calendar", "unsubscribeCalendarTitle"),
- calGetString("calendar",
- "unsubscribeCalendarMessage",
- [aCalendar.name]),
- {});
-
- if (ok) {
- var calMgr = getCalendarManager();
- calMgr.unregisterCalendar(aCalendar);
- calMgr.deleteCalendar(aCalendar);
- }
- }
-
- function ensureCalendarVisible(aCalendar) {
- var composite = getCompositeCalendar();
- if (!composite.getCalendar(aCalendar.uri)) {
- composite.addCalendar(aCalendar);
- }
- }
-
- /**
- * Calendar manager load/unload functions
- */
- function loadCalendarManager() {
- var calMgr = getCalendarManager();
- var composite = getCompositeCalendar();
- var calendars = calMgr.getCalendars({});
- var prefService = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefService);
- var branch = prefService.getBranch("").QueryInterface(Components.interfaces.nsIPrefBranch2);
-
- if (calendars.length == 0) {
- var url = makeURL("moz-profile-calendar://");
- var homeCalendar = calMgr.createCalendar("storage", url);
-
- calMgr.registerCalendar(homeCalendar);
- var name = calGetString("calendar", "homeCalendarName");
-
- homeCalendar.name = name;
- composite.addCalendar(homeCalendar);
-
- // Wrapping this in a try/catch block, as if any of the migration code
- // fails, the app may not load.
- if (getPrefSafe("calendar.migrator.enabled", true)) {
- try {
- gDataMigrator.checkAndMigrate();
- } catch (e) {
- Components.utils.reportError("Migrator error: " + e);
- }
- }
-
- calendars = [homeCalendar];
- }
-
- calendarListInitCategoryColors();
-
- // Set up the tree view
- var tree = document.getElementById("calendar-list-tree");
- calendarListTreeView.tree = tree;
- tree.view = calendarListTreeView;
-
- calMgr.addObserver(calendarManagerObserver);
- composite.addObserver(calendarManagerCompositeObserver);
- branch.addObserver("calendar.", calendarManagerObserver, false);
-
- // The calendar manager will not notify for existing calendars. Go through
- // them all and set up manually.
- for each (var calendar in calendars) {
- calendarManagerObserver.initializeCalendar(calendar);
- }
- }
-
- function unloadCalendarManager() {
- calendarManagerObserver.unload();
- var calMgr = getCalendarManager();
- var composite = getCompositeCalendar();
- var prefService = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefService);
- var branch = prefService.getBranch("").QueryInterface(Components.interfaces.nsIPrefBranch2);
-
- branch.removeObserver("calendar.", calendarManagerObserver);
- composite.removeObserver(calendarManagerCompositeObserver);
- calMgr.removeObserver(calendarManagerObserver);
- }
-
- /**
- * Color specific functions
- */
- var gCachedStyleSheet;
- function calendarListInitCategoryColors() {
- var calendars = getCalendarManager().getCalendars({});
- if (!gCachedStyleSheet) {
- var cssUri = "chrome://calendar/content/calendar-view-bindings.css";
- gCachedStyleSheet = getStyleSheet(cssUri);
- }
-
- var prefService = Components.classes["@mozilla.org/preferences-service;1"]
- .getService(Components.interfaces.nsIPrefService);
- var categoryPrefBranch = prefService.getBranch("calendar.category.color.");
- var categories = categoryPrefBranch.getChildList("", {});
-
- // check category preference name syntax
- categories = calendarConvertObsoleteColorPrefs(categoryPrefBranch, categories);
-
- // Update all categories
- for each (var category in categories) {
- updateStyleSheetForObject(category, gCachedStyleSheet);
- }
- }
-
- /**
- * Remove illegally formatted category names from the array coloredCategories
- * so they don't cause CSS errors. For each illegal colored category c, if
- * its color preference has not yet been replaced with a converted preference
- * with key formatStringForCSSRule(c), create the preference with the
- * converted key and with the previous preference value, and clear the old
- * preference. (For most users who upgrade and do not later add colors with a
- * downgrade version, this should convert any illegal preferences once, so
- * future runs have no illegal preferences.)
- * @param categoryPrefBranch prefBranch for "calendar.category.color."
- * @param coloredCategories array of preference name suffixes under the prefBranch.
- * @return same array with each illegal name replaced with formatted name if
- * it doesn't already exist, or simply removed from array if it does.
- */
- function calendarConvertObsoleteColorPrefs(categoryPrefBranch, coloredCategories) {
- for (var i in coloredCategories) {
- var category = coloredCategories[i];
- if (category.search(/[^_0-9a-z-]/) != -1) {
- var categoryFix = formatStringForCSSRule(category);
- if (!categoryPrefBranch.prefHasUserValue(categoryFix)) {
- var color = categoryPrefBranch.getCharPref(category);
- categoryPrefBranch.setCharPref(categoryFix, color);
- categoryPrefBranch.clearUserPref(category); // not usable
- coloredCategories[i] = categoryFix; // replace illegal name
- } else {
- coloredCategories.splice(i, 1); // remove illegal name
- }
- }
- }
- return coloredCategories;
- }
-
- function calendarListUpdateColor(aCalendar) {
- var selectorPrefix = "treechildren::-moz-tree-cell";
-
- var color = aCalendar.getProperty("color");
- if (!color) {
- return;
- }
- var selector = selectorPrefix + "color-" + color.substr(1);
-
- for (var i = 0; i < gCachedStyleSheet.cssRules.length; i++) {
- var thisrule = gCachedStyleSheet.cssRules[i];
- if (thisrule.selectorText && thisrule.selectorText == selector) {
- return;
- }
- }
-
- var ruleString = selectorPrefix + "(color-" + color.substr(1) + ") { }";
-
- var rule = gCachedStyleSheet
- .insertRule(ruleString, gCachedStyleSheet.cssRules.length);
-
- gCachedStyleSheet.cssRules[rule].style.backgroundColor = color;
- return;
- }
-
- /**
- * Calendar Tree View
- */
- var calendarListTreeView = {
- mCalendarList: [],
- tree: null,
- treebox: null,
- mContextElement: null,
-
- QueryInterface: function cLTV_QueryInterface(aIID) {
- return doQueryInterface(this, calendarListTreeView.__proto__, aIID,
- [Components.interfaces.nsISupports,
- Components.interfaces.nsITreeView]);
- },
-
- /**
- * High-level calendar tree manipulation
- */
-
- findIndex: function cLTV_findIndex(aCalendar) {
- for (var i = 0; i < this.mCalendarList.length; i++) {
- if (this.mCalendarList[i].id == aCalendar.id) {
- return i;
- }
- }
- return -1;
- },
-
- findIndexByUri: function cLTV_findIndexByUri(aUri) {
- for (var i = 0; i < this.mCalendarList.length; i++) {
- if (this.mCalendarList[i].uri.equals(aUri)) {
- return i;
- }
- }
- return -1;
- },
-
- addCalendar: function cLTV_addCalendar(aCalendar) {
- var composite = getCompositeCalendar();
- this.mCalendarList.push(aCalendar);
- calendarListUpdateColor(aCalendar);
- this.treebox.rowCountChanged(this.mCalendarList.length - 1, 1);
-
- if (!composite.defaultCalendar ||
- aCalendar.id == composite.defaultCalendar.id) {
- this.tree.view.selection.select(this.mCalendarList.length - 1);
- }
- },
-
- removeCalendar: function cLTV_removeCalendar(aCalendar) {
- var index = this.findIndex(aCalendar);
- if (index < 0) {
- return;
- }
-
- this.mCalendarList.splice(index, 1);
- this.treebox.rowCountChanged(index, -1);
-
- if (index == this.rowCount) {
- index--;
- }
-
- this.tree.view.selection.select(index);
- },
-
- updateCalendar: function cLTV_updateCalendar(aCalendar) {
- var index = this.findIndex(aCalendar);
- this.treebox.invalidateRow(index);
- },
-
- getCalendarFromEvent: function cLTV_getCalendarFromEvent(event,
- aCol,
- aRow) {
- if (event.clientX && event.clientY) {
- // If we have a client point, get the row directly from the client
- // point.
- aRow = aRow || {};
- this.treebox.getCellAt(event.clientX,
- event.clientY,
- aRow,
- aCol || {},
- {});
-
- } else {
- // The event is probably coming from a context menu oncommand
- // handler. We saved the row and column where the context menu
- // showed up in setupContextMenu().
- aCol = { value: this.mContextElement.column };
- aRow = { value: this.mContextElement.row };
- }
- return aRow && aRow.value > -1 && this.mCalendarList[aRow.value];
- },
-
- /**
- * nsITreeView methods and properties
- */
- get rowCount() {
- return this.mCalendarList.length;
- },
-
- getRowProperties: function cLTV_getRowProperties(aRow, aProps) {},
-
- getCellProperties: function cLTV_getCellProperties(aRow, aCol, aProps) {
- var calendar = this.mCalendarList[aRow];
- var composite = getCompositeCalendar();
-
- switch (aCol.id) {
- case "calendar-list-tree-checkbox":
- if (composite.getCalendar(calendar.uri)) {
- aProps.AppendElement(getAtomFromService("checked"));
- } else {
- aProps.AppendElement(getAtomFromService("unchecked"));
- }
- break;
- case "calendar-list-tree-color":
- // Get the calendar color
- var color = calendar.getProperty("color");
- color = color && color.substr(1);
-
- // Set up the calendar color (background)
- var bgColorProp = "color-" + (color || "default");
- aProps.AppendElement(getAtomFromService(bgColorProp));
-
- // Set a property to get the contrasting text color (foreground)
- var fgColorProp = getContrastingTextColor(color || "a8c2e1");
- aProps.AppendElement(getAtomFromService(fgColorProp));
-
- // Set up the readonly symbol
- if (calendar.readOnly) {
- aProps.AppendElement(getAtomFromService("readOnly"));
- }
-
- break;
- }
- },
-
- getColumnProperties: function cLTV_getColumnProperties(a, aProps) {},
-
- isContainer: function cLTV_isContainer(aRow) {
- return false;
- },
-
- isContainerOpen: function cLTV_isContainerOpen(aRow) {
- return false;
- },
-
- isContainerEmpty: function cLTV_isContainerEmpty(aRow) {
- return false;
- },
-
- isSeparator: function cLTV_isSeparator(aRow) {
- return false;
- },
-
- isSorted: function cLTV_isSorted(aRow) {
- return false;
- },
-
- canDrop: function cLTV_canDrop(aRow, aOrientation) {
- return false;
- },
-
- drop: function cLTV_drop(aRow, aOrientation) {},
-
- getParentIndex: function cLTV_getParentIndex(aRow) {
- return -1;
- },
-
- hasNextSibling: function cLTV_hasNextSibling(aRow, aAfterIndex) {},
-
- getLevel: function cLTV_getLevel(aRow) {
- return 0;
- },
-
- getImageSrc: function cLTV_getImageSrc(aRow, aOrientation) {},
-
- getProgressMode: function cLTV_getProgressMode(aRow, aCol) {},
-
- getCellValue: function cLTV_getCellValue(aRow, aCol) {
- var calendar = this.mCalendarList[aRow];
- var composite = getCompositeCalendar();
-
- switch (aCol.id) {
- case "calendar-list-tree-checkbox":
- return composite.getCalendar(calendar.uri) ? "true" : "false";
- case "calendar-list-tree-color":
- // The value of this cell shows the calendar readonly state
- return (calendar.readOnly ? "true" : "false");
- }
- return null;
- },
-
- getCellText: function cLTV_getCellText(aRow, aCol) {
- var calendar = this.mCalendarList[aRow];
- var composite = getCompositeCalendar();
-
- switch (aCol.id) {
- case "calendar-list-tree-calendar":
- return this.mCalendarList[aRow].name;
-
- }
- return "";
- },
-
- setTree: function cLTV_setTree(aTreeBox) {
- this.treebox = aTreeBox;
- },
-
- toggleOpenState: function cLTV_toggleOpenState(aRow) {},
-
- cycleHeader: function cLTV_cycleHeader(aCol) { },
-
- cycleCell: function cLTV_cycleCell(aRow, aCol) {
- var calendar = this.mCalendarList[aRow];
- var composite = getCompositeCalendar();
-
- switch (aCol.id) {
- case "calendar-list-tree-checkbox":
- if (composite.getCalendar(calendar.uri)) {
- composite.removeCalendar(calendar.uri);
- } else {
- composite.addCalendar(calendar);
- }
- break;
- case "calendar-list-tree-color":
- // Clicking on the color should toggle the readonly state.
- calendar.readOnly = !calendar.readOnly;
- break;
- }
- this.treebox.invalidateRow(aRow);
- },
-
- isEditable: function cLTV_isEditable(aRow, aCol) {
- return false;
- },
-
- setCellValue: function cLTV_setCellValue(aRow, aCol, aValue) {
- var calendar = this.mCalendarList[aRow];
- var composite = getCompositeCalendar();
-
- switch (aCol.id) {
- case "calendar-list-tree-checkbox":
- if (aValue == "true") {
- composite.addCalendar(calendar);
- } else {
- composite.removeCalendar(calendar);
- }
- break;
- case "calendar-list-tree-color":
- calendar.readOnly = (aValue == "true");
- break;
- default:
- return null;
- }
- return aValue;
- },
-
- setCellText: function cLTV_setCellText(aRow, aCol, aValue) {},
-
- performAction: function cLTV_performAction(aAction) {},
-
- performActionOnRow: function cLTV_performActionOnRow(aAction, aRow) {},
-
- performActionOnCell: function cLTV_performActionOnCell(aAction, aRow, aCol) {},
-
- /**
- * Calendar Tree Events
- */
- onKeyPress: function cLTV_onKeyPress(event) {
- const kKE = Components.interfaces.nsIDOMKeyEvent;
- switch (event.keyCode || event.which) {
- case kKE.DOM_VK_DELETE:
- promptDeleteCalendar(getSelectedCalendar());
- break;
- case kKE.DOM_VK_SPACE:
- if (this.tree.currentIndex > -1 ) {
- var cbCol =
- this.treebox.columns
- .getNamedColumn("calendar-list-tree-checkbox");
- this.cycleCell(this.tree.currentIndex, cbCol);
- }
- break;
- }
- },
-
- onDoubleClick: function cLTV_onDoubleClick(event) {
- var col = {};
- var calendar = this.getCalendarFromEvent(event, col);
- if (event.button != 0 ||
- (col.value && col.value.id == "calendar-list-tree-checkbox")) {
- // Only left clicks that are not on the checkbox column
- return;
- }
- if (calendar) {
- openCalendarProperties(calendar, null);
- } else {
- openCalendarWizard();
- }
- },
-
- onSelect: function cLTV_onSelect(event) {
- // The select event should only fire when an item is actually selected,
- // therefore we can assume that getSelectedCalendar() returns a
- // calendar.
- var composite = getCompositeCalendar();
- composite.defaultCalendar = getSelectedCalendar();
- },
-
- setupContextMenu: function cLTV_setupContextMenu(event) {
- var col = {};
- var row = {};
- var calendar;
- var calendars = getCalendarManager().getCalendars({});
-
- if (document.popupNode.localName == "tree") {
- // Using VK_APPS to open the context menu will target the tree
- // itself. In that case we won't have a client point even for
- // opening the context menu. The "target" element should then be the
- // selected element.
- row.value = this.tree.currentIndex;
- col.value = this.treebox.columns
- .getNamedColumn("calendar-list-tree-calendar");
- calendar = this.mCalendarList[row.value];
- } else {
- // Using the mouse, the context menu will open on the treechildren
- // element. Here we can use client points.
- calendar = this.getCalendarFromEvent(event, col, row);
- }
-
- if (col.value && col.value.id == "calendar-list-tree-checkbox") {
- // Don't show the context menu if the checkbox was clicked.
- return false;
- }
-
- // We need to save the row to return the correct calendar in
- // getCalendarFromEvent()
- this.mContextElement = {
- row: row && row.value,
- column: col && col.value
- };
-
- // Only enable calendar search if there's actually the chance of finding something:
- document.getElementById("list-calendars-context-find").setAttribute(
- "collapsed", (getCalendarSearchService().getProviders({}).length > 0 ? "false" : "true"));
-
- if (calendar) {
- document.getElementById("list-calendars-context-edit")
- .removeAttribute("disabled");
- document.getElementById("list-calendars-context-publish")
- .removeAttribute("disabled");
- // Only enable the delete calendars item if there is more than one
- // calendar. We don't want to have the last calendar deleted.
- if (calendars.length > 1) {
- document.getElementById("list-calendars-context-delete")
- .removeAttribute("disabled");
- }
- } else {
- document.getElementById("list-calendars-context-edit")
- .setAttribute("disabled", "true");
- document.getElementById("list-calendars-context-publish")
- .setAttribute("disabled", "true");
- document.getElementById("list-calendars-context-delete")
- .setAttribute("disabled", "true");
- }
- return true;
- }
- };
-
- var calendarManagerCompositeObserver = {
- QueryInterface: function cMCO_QueryInterface(aIID) {
- if (!aIID.equals(Components.interfaces.calICompositeObserver) &&
- !aIID.equals(Components.interfaces.calIObserver) &&
- !aIID.equals(Components.interfaces.nsISupports)) {
- throw Components.results.NS_ERROR_NO_INTERFACE;
- }
- return this;
- },
-
- onCalendarAdded: function cMO_onCalendarAdded(aCalendar) {
- // Make sure the checkbox state is updated
- var index = calendarListTreeView.findIndex(aCalendar);
- calendarListTreeView.treebox.invalidateRow(index);
- },
-
- onCalendarRemoved: function cMO_onCalendarRemoved(aCalendar) {
- // Make sure the checkbox state is updated
- var index = calendarListTreeView.findIndex(aCalendar);
- calendarListTreeView.treebox.invalidateRow(index);
- },
-
- onDefaultCalendarChanged: function cMO_onDefaultCalendarChanged(aCalendar) {
- },
-
- // calIObserver. Note that each registered calendar uses this observer, not
- // only the composite calendar.
- onStartBatch: function cMO_onStartBatch() { },
- onEndBatch: function cMO_onEndBatch() { },
- onLoad: function cMO_onLoad() { },
-
- // TODO: remove these temporary caldav exclusions when it is safe to do so
- // needed to allow cadav refresh() to update w/o forcing visibility
- onAddItem: function cMO_onAddItem(aItem) {
- if (aItem.calendar.type != "caldav") {
- ensureCalendarVisible(aItem.calendar);
- }
- },
-
- onModifyItem: function cMO_onModifyItem(aNewItem, aOldItem) {
- if (aNewItem.calendar.type != "caldav") {
- ensureCalendarVisible(aNewItem.calendar);
- }
- },
-
- onDeleteItem: function cMO_onDeleteItem(aDeletedItem) { },
- onError: function cMO_onError(aErrNo, aMessage) { },
-
- onPropertyChanged: function cMO_onPropertyChanged(aCalendar,
- aName,
- aValue,
- aOldValue) {},
- onPropertyDeleting: function cMO_onPropertyDeleting(aCalendar,
- aName) {}
- }
-
- var calendarManagerObserver = {
- mDefaultCalendarItem: null,
-
- QueryInterface: function cMO_QueryInterface(aIID) {
- if (!aIID.equals(Components.interfaces.calICalendarManagerObserver) &&
- !aIID.equals(Components.interfaces.calIObserver) &&
- !aIID.equals(Components.interfaces.nsIObserver) &&
- !aIID.equals(Components.interfaces.nsISupports)) {
- throw Components.results.NS_ERROR_NO_INTERFACE;
- }
- return this;
- },
-
- /**
- * Set up the UI for a new calendar.
- *
- * @param aCalendar The calendar to add.
- */
- initializeCalendar: function cMO_initializeCalendar(aCalendar) {
- calendarListTreeView.addCalendar(aCalendar);
-
- updateStyleSheetForObject(aCalendar, gCachedStyleSheet);
- calendarListUpdateColor(aCalendar);
-
- // Watch the calendar for changes, to ensure its visibility when adding
- // or changing items.
- aCalendar.addObserver(this);
-
- // Update the calendar commands for number of remote calendars and for
- // more than one calendar
- document.commandDispatcher.updateCommands("calendar_commands");
- },
-
- unload: function cMO_unload() {
- var calendars = getCalendarManager().getCalendars({});
- for each (var calendar in calendars) {
- calendar.removeObserver(this);
- }
- },
-
- setupWritableCalendars: function cMO_setupWritableCalendars() {
- var nodes = document.getElementsByAttribute("disable-when-no-writable-calendars", "true");
- for (var i = 0; i < nodes.length; i++) {
- if (this.mWritableCalendars < 1) {
- nodes[i].setAttribute("disabled", "true");
- } else {
- nodes[i].removeAttribute("disabled");
- }
- }
- },
-
- // calICalendarManagerObserver
- onCalendarRegistered: function cMO_onCalendarRegistered(aCalendar) {
- this.initializeCalendar(aCalendar);
- var composite = getCompositeCalendar();
- var inComposite = aCalendar.getProperty(composite.prefPrefix +
- "-in-composite");
- if ((inComposite === null) || inComposite) {
- composite.addCalendar(aCalendar);
- }
- },
-
- onCalendarUnregistering: function cMO_onCalendarUnregistering(aCalendar) {
- var calendars = getCalendarManager().getCalendars({});
-
- calendarListTreeView.removeCalendar(aCalendar);
- aCalendar.removeObserver(this);
-
- // Make sure the calendar is removed from the composite calendar
- getCompositeCalendar().removeCalendar(aCalendar.uri);
-
- // Update commands to disallow deleting the last calendar and only
- // allowing reload remote calendars when there are remote calendars.
- document.commandDispatcher.updateCommands("calendar_commands");
- },
-
- onCalendarDeleting: function cMO_onCalendarDeleting(aCalendar) {
- },
-
- // calIObserver. Note that each registered calendar uses this observer, not
- // only the composite calendar.
- onStartBatch: function cMO_onStartBatch() { },
- onEndBatch: function cMO_onEndBatch() { },
- onLoad: function cMO_onLoad() { },
-
- // TODO: remove these temporary caldav exclusions when it is safe to do so
- // needed to allow cadav refresh() to update w/o forcing visibility
- onAddItem: function cMO_onAddItem(aItem) {
- if (aItem.calendar.type != "caldav") {
- ensureCalendarVisible(aItem.calendar);
- }
- },
-
- onModifyItem: function cMO_onModifyItem(aNewItem, aOldItem) {
- if (aNewItem.calendar.type != "caldav") {
- ensureCalendarVisible(aNewItem.calendar);
- }
- },
-
- onDeleteItem: function cMO_onDeleteItem(aDeletedItem) { },
- onError: function cMO_onError(aErrNo, aMessage) { },
-
- onPropertyChanged: function cMO_onPropertyChanged(aCalendar,
- aName,
- aValue,
- aOldValue) {
- switch (aName) {
- case "color":
- updateStyleSheetForObject(aCalendar, gCachedStyleSheet);
- calendarListUpdateColor(aCalendar);
- // Fall through, update item in any case
- case "name":
- calendarListTreeView.updateCalendar(aCalendar);
- break;
- case "readOnly":
- calendarListTreeView.updateCalendar(aCalendar);
- // Fall through, update commands in any cases.
- case "requiresNetwork":
- document.commandDispatcher.updateCommands("calendar_commands");
- break;
- }
- },
-
- onPropertyDeleting: function cMO_onPropertyDeleting(aCalendar,
- aName) {
- // Since the old value is not used directly in onPropertyChanged,
- // but should not be the same as the value, set it to a different
- // value.
- this.onPropertyChanged(aCalendar, aName, null, null);
- },
-
- // nsIObserver
- observe: function cMO_observe(aSubject, aTopic, aPrefName) {
-
- switch (aPrefName) {
- case "calendar.week.start":
- getMinimonth().refreshDisplay(true);
- break;
- case "calendar.date.format":
- var view = currentView();
- var day = view.selectedDay;
- if (day) {
- // The view may not be initialized, only refresh if there is
- // a selected day.
- view.goToDay(day);
- }
-
- if (isSunbird()) {
- refreshEventTree();
- }
- toDoUnifinderRefresh();
- break;
- case "calendar.timezone.local":
- var subject = aSubject.QueryInterface(Components.interfaces.nsIPrefBranch2);
- gDefaultTimezone = subject.getCharPref(aPrefName);
-
- var view = currentView();
- var day = view.selectedDay;
- if (day) {
- // The view may not be initialized, only refresh if there is
- // a selected day.
- view.goToDay(day);
- }
-
- if (isSunbird()) {
- refreshEventTree();
- }
- toDoUnifinderRefresh();
- break;
- default :
- break;
- }
-
- // Since we want to take care of all categories, this must be done
- // extra.
- if (aPrefName.substring(0, 24) == "calendar.category.color.") {
- var categoryName = aPrefName.substring(24);
- updateStyleSheetForObject(categoryName, gCachedStyleSheet);
- }
- }
- };
-
- function openCalendarSubscriptionsDialog() {
- // the dialog will reset this to auto when it is done loading
- window.setCursor("wait");
-
- // open the dialog modally
- window.openDialog("chrome://calendar/content/calendar-subscriptions-dialog.xul",
- "_blank",
- "chrome,titlebar,modal,resizable");
- }
-
- /**
- * Calendar Offline Manager
- */
- var calendarOfflineManager = {
- QueryInterface: function cOM_QueryInterface(aIID) {
- return doQueryInterface(this, calendarOfflineManager.prototype, aIID,
- [Components.interfaces.nsIObserver, Components.interfaces.nsISupports]);
- },
-
- init: function cOM_init() {
- if (this.initialized) {
- throw Components.results.NS_ERROR_ALREADY_INITIALIZED;
- }
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- os.addObserver(this, "network:offline-status-changed", false);
-
- this.updateOfflineUI(!this.isOnline());
- this.initialized = true;
- },
-
- uninit: function cOM_uninit() {
- if (!this.initialized) {
- throw Components.results.NS_ERROR_NOT_INITIALIZED;
- }
- var os = Components.classes["@mozilla.org/observer-service;1"]
- .getService(Components.interfaces.nsIObserverService);
- os.removeObserver(this, "network:offline-status-changed", false);
- this.initialized = false;
- },
-
- isOnline: function cOM_isOnline() {
- return (!getIOService().offline);
-
- },
-
- updateOfflineUI: function cOM_updateOfflineUI(aIsOffline) {
- // Refresh the current view
- currentView().goToDay(currentView().selectedDay);
-
- // Set up disabled locks for offline
- document.commandDispatcher.updateCommands("calendar_commands");
- },
-
- observe: function cOM_observe(aSubject, aTopic, aState) {
- if (aTopic == "network:offline-status-changed") {
- this.updateOfflineUI(aState == "offline");
- }
- }
- };
-